package com.xbh.management.security;



import com.xbh.common.utils.RedisUtils;
import com.xbh.management.filter.TokenLoginFilter;
import com.xbh.management.utils.MD5Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.net.URLConnection;

/**
 * @program: management-center
 * @description: 自定义用户登录验证逻辑
 * AuthenticationProvider是用户自定义身份认证,认证流程顶级接口。唯一作用即使用来进行身份验证
 * Spring security 默认只会处理用户名和密码信息
 * WebAuthenticationDetails: 该类提供了获取用户登录时携带的额外信息的功能，默认提供了 remoteAddress 与 sessionId 信息。
 * @author: 许宝华
 * @create: 2021-10-06 14:53
 */

/**
 * 自定义校验规则
 */
@Component
public class LocalAuthenticationProvider implements AuthenticationProvider {

    private static Logger log = LoggerFactory.getLogger(LocalAuthenticationProvider.class);

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private DefaultPasswordEncoderUtil defaultPasswordEncoderUtil;

    @Autowired
    private RedisUtils redisUtils;



    @Override
    public Authentication authenticate(Authentication authentication) throws BadCredentialsException {
        log.info("进入自定义验证规则");
        String username = authentication.getName();
        String password = (String)authentication.getCredentials();
        UserWebAuthenticationDetails details = (UserWebAuthenticationDetails) authentication.getDetails();
        // 获取Request, 获取其他参数信息
        String code = details.getCode();
        //验证码比较
        String redisCode = (String)redisUtils.get("code");
        if(redisCode.toString().equalsIgnoreCase(code)){
            //去找自己实现UserDetails的实现类
            UserDetails userDetails = userDetailsService.loadUserByUsername(username);

            if(defaultPasswordEncoderUtil.matches(password,userDetails.getPassword())){
                //用户名密码校验成功
                return new UsernamePasswordAuthenticationToken(userDetails, password, userDetails.getAuthorities());
            }
            log.info("用户名或密码不正确");
            throw new BadCredentialsException("用户名或密码不正确!");
        }

        log.info("验证码不正确");
        throw new BadCredentialsException("验证码不正确!");

    }


    /**
     * supports函数用来指明该Provider是否适用于该类型的认证，如果不合适，则寻找另一个Provider进行验证处理
     * @param authentication
     * @return
     */
    @Override
    public boolean supports(Class<?> authentication) {
        //和SpringSecurity
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }
}
